<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./Adder_Subtractor_Binary.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="A signed binary integer adder/subtractor, with `carry_in`, `carry_out`, `overflow`, and all the intermediate `carries` into each bit position (see [Carry-In Calculator](./CarryIn_Binary.html) for their uses).">
<title>Adder Subtractor Binary</title>
</head>
<body>

<p class="inline bordered"><b><a href="./Adder_Subtractor_Binary.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>

<h1>Binary Integer Adder/Subtractor</h1>
<p>A signed binary integer adder/subtractor, with <code>carry_in</code>, <code>carry_out</code>,
 <code>overflow</code>, and all the intermediate <code>carries</code> into each bit position (see
 <a href="./CarryIn_Binary.html">Carry-In Calculator</a> for their uses).</p>
<p>Addition/subtraction is selected with <code>add_sub</code>: 0 for an add
 (<code>A+B+carry_in</code>), and 1 for a subtract (<code>A-B-carry_in</code>). This assignment
 conveniently matches the convention of sign bits. <em>Note that the <code>overflow</code>
 bit is only meaningful for signed numbers. For unsigned numbers, use
 <code>carry_out</code> instead.</em></p>
<p>On FPGAs, you are much better off letting the CAD tool infer the
 add/subtract circuitry from the <code>+</code> or <code>-</code> operator itself, rather than
 structurally describing it in Boolean logic, as the latter may not get
 mapped to the fast, dedicated ripple-carry hardware. Wrapping all this into
 a module hides the width adjustments necessary to get a warning-free
 synthesis of carry logic, and enables correct carry and overflow
 calculations.</p>
<p>Because we handle the carry bits ourselves and do everything through an
 unsigned addition, we don't depend on the tricky Verilog behaviour where
 all terms of an expression must be declared signed else the expression is
 silently evaluated as unsigned!</p>

<pre>
`default_nettype none

module <a href="./Adder_Subtractor_Binary.html">Adder_Subtractor_Binary</a>
#(
    parameter       WORD_WIDTH = 0
)
(
    input   wire                        add_sub,    // 0/1 -> A+B/A-B
    input   wire                        carry_in,
    input   wire    [WORD_WIDTH-1:0]    A,
    input   wire    [WORD_WIDTH-1:0]    B,
    output  reg     [WORD_WIDTH-1:0]    sum,
    output  reg                         carry_out,
    output  wire    [WORD_WIDTH-1:0]    carries,
    output  reg                         overflow
);

    localparam ZERO = {WORD_WIDTH{1'b0}};
    localparam ONE  = {{WORD_WIDTH-1{1'b0}},1'b1};

    initial begin
        sum         = ZERO;
        carry_out   = 1'b0;
        overflow    = 1'b0;
    end
</pre>

<p>Extend the <code>carry_in</code> to the extended word width, as both signed (0 or -1)
 and unsigned (0 or 1) words, so we don't have width mismatches nor rely on
 sign extension, which is full of pitfalls, and would trigger useless
 warnings in the CAD tools.</p>

<pre>
    wire [WORD_WIDTH-1:0] carry_in_extended_unsigned;
    wire [WORD_WIDTH-1:0] carry_in_extended_signed;

    <a href="./Width_Adjuster.html">Width_Adjuster</a>
    #(
        .WORD_WIDTH_IN  (1),
        .SIGNED         (0),
        .WORD_WIDTH_OUT (WORD_WIDTH)
    )
    extend_carry_in_unsigned
    (
        .original_input     (carry_in),
        .adjusted_output    (carry_in_extended_unsigned)
    );

    <a href="./Width_Adjuster.html">Width_Adjuster</a>
    #(
        .WORD_WIDTH_IN  (1),
        .SIGNED         (1),
        .WORD_WIDTH_OUT (WORD_WIDTH)
    )
    extend_carry_in_signed
    (
        .original_input     (carry_in),
        .adjusted_output    (carry_in_extended_signed)
    );
</pre>

<p>Depending on the value of <code>add_sub</code>, generate the bit-negation of <code>B</code> and
 the necessary offset for <code>B</code>'s 2's-complement arithmetic negation, and
 select the correct <code>carry_in</code> value. We do this separately to have the
 negated <code>B</code> available later for the calculations of the <code>carries</code> and of
 the <code>overflow</code>.</p>

<pre>
    reg [WORD_WIDTH-1:0] B_selected         = ZERO;
    reg [WORD_WIDTH-1:0] negation_offset    = ZERO;
    reg [WORD_WIDTH-1:0] carry_in_selected  = ZERO;

    always @(*) begin
        B_selected          = (add_sub == 1'b0) ? B    : ~B;
        negation_offset     = (add_sub == 1'b0) ? ZERO : ONE;
        carry_in_selected   = (add_sub == 1'b0) ? carry_in_extended_unsigned : carry_in_extended_signed;
    end
</pre>

<p>And add as usual, with subtraction expressed as <code>A+((~B)+1)</code>, so as to
 generate the correct <code>carries</code> for each bit position.</p>
<p>Since the left-hand side is one bit wider to hold <code>carry_out</code>, all other
 terms are implicitly extended to that width (see Verilog LRM, IEEE
 1364-2001, Section 4.4, "Expression bit lengths").  However, since I avoid
 implicit width extension as a way to reduce warnings and prevent bugs,
 let's prepend a zero to all the unsigned right-hand terms to make all
 widths match and force a simple, unsigned addition.</p>
<p>We could have done this more concisely by first widening all terms to
 <code>WORD_WIDTH+1</code>, then selecting addition/subtraction in one line, but we
 need the possibly negated <code>B</code> later for the <code>carries</code> and <code>overflow</code>
 calculation.</p>

<pre>
    always @(*) begin
        {carry_out, sum} = {1'b0, A} + {1'b0, B_selected} + {1'b0, negation_offset} + {1'b0, carry_in_selected};
    end
</pre>

<p>Finally, recover the carry <em>into</em> each bit from the selected addition
 terms.  The first bit of <code>carries</code> is the same as <code>carry_in</code>.  We must do
 this here rather than in the enclosing module, since if you are
 subtracting, the negated <code>B</code> term is not externally available.</p>

<pre>
    <a href="./CarryIn_Binary.html">CarryIn_Binary</a>
    #(
        .WORD_WIDTH (WORD_WIDTH)
    )
    per_bit
    (
        .A          (A),
        .B          (B_selected),
        .sum        (sum),
        .carryin    (carries)
    );
</pre>

<p>And compute the signed overflow, which happens when the carry into and out
 from the MSB do not agree.</p>

<pre>
    always @(*) begin
        overflow = (carries [WORD_WIDTH-1] != carry_out);
    end

endmodule
</pre>

<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>

